home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / util / misc / TeeHdl10.lha / TeeHandler / tee-handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-07  |  5.3 KB  |  229 lines

  1. /*
  2.     tee-handler.c
  3.  
  4.     This is a `T' pipe for AmigaDOS. Now, for example, you can display
  5.     the shell output of a program in a console window and, at the
  6.     same time, capture it into a file.
  7.  
  8.  
  9.     This stuff is explicitly declared as Public Domain.
  10.     07-Sep-96 by Michael Krause <rawstyle@blackbox.dame.de>
  11. */
  12.  
  13. #include <exec/exec.h>
  14. #include <dos/dos.h>
  15. #include <dos/filehandler.h>
  16.  
  17. #include <proto/exec.h>
  18. #include <proto/dos.h>
  19.  
  20. char verstring[] = "$VER: tee-handler v1.0 (7.9.96)";
  21.  
  22. static struct DosLibrary *DOSBase;
  23. static struct ExecBase *SysBase;
  24.  
  25. static char colonchar='%', divchar='@';
  26.  
  27. struct fharg1
  28. {
  29.     ULONG count;
  30.     BPTR fh[1];
  31. };
  32.  
  33. static void ReturnPacket(struct DosPacket *, struct MsgPort *, LONG, LONG);
  34. static struct DosPacket *GetPacket(struct MsgPort *);
  35. static STRPTR where(STRPTR, char);
  36. static void strncpy(STRPTR, STRPTR, UWORD);
  37. static void replace(STRPTR);
  38.  
  39. /*----------------- THE ENTRY POINT ------------------------------------*/
  40.  
  41. void entry(void)
  42. {
  43.     struct MsgPort *procport, *packetport;
  44.     struct DosPacket *packet;
  45.     struct DeviceNode *devnode;
  46.     LONG error=0, err2;
  47.     ULONG i;
  48.     STRPTR names, name1, name2;
  49.     struct fharg1 *thisfharg1;
  50.     BPTR fh;
  51.  
  52.     SysBase = *(APTR*)4;
  53.  
  54.     procport = &((struct Process *)FindTask(NULL))->pr_MsgPort;
  55.     WaitPort(procport);
  56.     packet = GetPacket(procport);
  57.  
  58.     if(DOSBase = (struct DosLibrary *)OpenLibrary(DOSNAME, 36))
  59.     {
  60.         /* We need a new MsgPort because the "built-in" one would interfer
  61.             with our dos.library calls. */
  62.         if(packetport = CreateMsgPort())
  63.         {
  64.             devnode = (struct DeviceNode *)BADDR(packet->dp_Arg3);
  65.             packet->dp_Arg4 = (LONG) packetport;
  66.             devnode->dn_Task = packetport;
  67.             ReturnPacket(packet, packetport, DOSTRUE, 0);
  68.  
  69.             /* Handler initialized, now process messages */
  70.             for(;;)
  71.             {
  72.                 WaitPort(packetport);
  73.                 packet=GetPacket(packetport);
  74.                 switch(packet->dp_Type)
  75.                 {
  76.                     case ACTION_FINDOUTPUT:
  77.                         err2 = ERROR_NO_FREE_STORE;
  78.  
  79.                         /* First copy the BSTR into a private buffer */
  80.                         name1 = (STRPTR)BADDR(packet->dp_Arg3);
  81.                         if(names = (STRPTR)AllocVec((*name1)+1, MEMF_ANY))
  82.                         {
  83.                             strncpy(names, name1+1, *name1);
  84.  
  85.                             /* Count destination files */
  86.                             name1 = where(names, ':');
  87.                             i = 1;
  88.                             while((name2=where(name1,divchar))!=name1)
  89.                             {
  90.                                 name1 = name2;
  91.                                 i++;
  92.                             }
  93.  
  94.                             /* Get private data space */
  95.                             if(thisfharg1 = (struct fharg1 *)AllocMem(4*i+1, MEMF_CLEAR))
  96.                             {
  97.                                 thisfharg1->count = i;
  98.  
  99.                                 err2 = ERROR_INVALID_COMPONENT_NAME;
  100.  
  101.                                 /* Open destination files */
  102.                                 name1 = where(names, ':');
  103.                                 for(i=0;i<thisfharg1->count;i++)
  104.                                 {
  105.                                     name2 = where(name1, divchar);
  106.                                     if(name2 != name1)
  107.                                         name2[-1] = '\0'; /* Terminate string (replace divchar by \0) */
  108.                                     replace(name1);
  109.  
  110.                                     if(where(name1, ':') == name1) /* Require an absolute path */
  111.                                         break;
  112.                                     if(!(thisfharg1->fh[i] = Open(name1, MODE_NEWFILE)))
  113.                                         break;
  114.                                     name1 = name2;
  115.                                 }
  116.  
  117.                                 if(i==thisfharg1->count)
  118.                                 {
  119.                                     /* Now all files successfully opened. */
  120.                                     fh = (BPTR)BADDR(packet->dp_Arg1);
  121.                                     ((struct FileHandle *)fh)->fh_Arg1 = (LONG)thisfharg1;
  122.                                     ((struct FileHandle *)fh)->fh_Port = DOSFALSE;
  123.                                     FreeVec(names);
  124.                                     ReturnPacket(packet, packetport, DOSTRUE, 0);
  125.                                     break;
  126.                                 }
  127.  
  128.                                 for(i=0;i<thisfharg1->count;i++)
  129.                                     if(fh=thisfharg1->fh[i])
  130.                                         Close(fh);
  131.                                 FreeMem(thisfharg1, 4*i+1);
  132.                             }
  133.                             FreeVec(names);
  134.                         }
  135.  
  136.                         ReturnPacket(packet, packetport, DOSFALSE, err2);
  137.                         break;
  138.  
  139.                     case ACTION_WRITE:
  140.                         thisfharg1 = (struct fharg1 *)packet->dp_Arg1;
  141.                         for(i=0;i<thisfharg1->count;i++)
  142.                             Write(thisfharg1->fh[i], (APTR)packet->dp_Arg2, packet->dp_Arg3);
  143.                         ReturnPacket(packet, packetport, packet->dp_Arg3, 0);
  144.                         break;
  145.  
  146.                     case ACTION_END:
  147.                         thisfharg1 = (struct fharg1 *)packet->dp_Arg1;
  148.                         for(i=0;i<thisfharg1->count;i++)
  149.                             Close(thisfharg1->fh[i]);
  150.                         FreeMem(thisfharg1, 4*i+1);
  151.                         ReturnPacket(packet, packetport, DOSTRUE, 0);
  152.                         /* This was easy, hmm? */
  153.                         break;
  154.  
  155.                     default:
  156.                         ReturnPacket(packet, packetport, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
  157.                         break;
  158.                 }
  159.             }
  160.  
  161.             devnode->dn_Task=NULL;
  162.         }
  163.         else error = ERROR_NO_FREE_STORE;
  164.         CloseLibrary((struct Library*)DOSBase);
  165.     }
  166.     else error = ERROR_OBJECT_NOT_FOUND;
  167.  
  168.     if(error)
  169.         ReturnPacket(packet, procport, DOSFALSE, error);
  170. }
  171.  
  172. /*----------------- SUBROUTINES ----------------------------------------*/
  173.  
  174. void ReturnPacket(struct DosPacket *packet, struct MsgPort *port, LONG res1, LONG res2)
  175. {
  176.     struct MsgPort *mp = packet->dp_Port;
  177.  
  178.     packet->dp_Port = port;
  179.     packet->dp_Res1 = res1;
  180.     packet->dp_Res2 = res2;
  181.  
  182.     PutMsg(mp, packet->dp_Link);
  183. }
  184.  
  185. struct DosPacket *GetPacket(struct MsgPort *port)
  186. {
  187.     struct Message *msg;
  188.  
  189.     if(msg = GetMsg(port))
  190.         return((struct DosPacket *)msg->mn_Node.ln_Name);
  191.     else
  192.         return(NULL);
  193. }
  194.  
  195. /* Find character in string and return address of first occurence + 1,
  196.    if not found, return full string */
  197. STRPTR where(STRPTR s, char x)
  198. {
  199.     char a,i=0;
  200.  
  201.     while(a=s[i++])
  202.         if(a==x) return(&s[i]);
  203.  
  204.     return(s);
  205. }
  206.  
  207. void strncpy(STRPTR a, STRPTR b, UWORD c)
  208. {
  209.     for(;;)
  210.     {
  211.         if((WORD)--c<0) break;
  212.         *a++ = *b++;
  213.     }
  214.     *a = '\0';
  215. }
  216.  
  217. /* Replace first colonchar with colon */
  218. void replace(STRPTR s)
  219. {
  220.     char c;
  221.  
  222.     while(c=*s++)
  223.         if(c==colonchar)
  224.         {
  225.             s[-1]=':';
  226.             return;
  227.         }
  228. }
  229.